<template>
  <div class="MyTable h-full flex-col">
    <MyQueryForm
      ref="$queryForm"
      :query-schemas="querySchemas"
      :query-format="queryFormat"
      @search="handleSearch"
      @reset="handleReset"
    >
      <template #handle>
        <slot name="handle"></slot>
      </template>
    </MyQueryForm>
    <n-data-table
      class="h-full"
      :remote="remote"
      :loading="loading"
      :columns="treatedColumns"
      :data="tableData"
      :row-key="(row) => row[rowKey]"
      :pagination="isPagination ? pagination : false"
      :render-cell="renderCell"
      :bordered="false"
      :scroll-x="scrollX"
      flex-height
      v-bind="attrs"
    >
      <template #empty>
        <div class="flex-col items-center">
          <img :src="appStore.nodataImg" />
          <div :class="['text-14 font-400', appStore.isDeep ? 'color-#FFFFFFCC' : 'color-#817E92']">
            暂无数据
          </div>
        </div>
      </template>
    </n-data-table>
  </div>
</template>

<script setup lang="jsx">
import { useAppStore } from '@/store'
import { utils, writeFile } from 'xlsx'
defineOptions({ name: 'MyTable' })
const attrs = useAttrs()
const props = defineProps({
  /**
   * @remote true: 后端分页  false： 前端分页
   */
  remote: {
    type: Boolean,
    default: true,
  },
  /**
   * @remote 是否分页
   */
  isPagination: {
    type: Boolean,
    default: true,
  },
  rowKey: {
    type: String,
    default: 'id',
  },
  columns: {
    type: Array,
    required: true,
  },
  getData: {
    type: Function,
    required: true,
  },
  selection: {
    type: Boolean,
    default: false,
  },
  index: {
    type: Boolean,
    default: false,
  },
  autoLoad: {
    type: Boolean,
    default: true,
  },
  tooltipWidth: {
    type: Number,
    default: 300,
  },
  cellWidth: {
    type: Number,
    default: 150,
  },
  indexWidth: {
    type: Number,
    default: 60,
  },
  queryFormat: {
    type: Function,
    default: null,
  },
  querySchemas: {
    type: Array,
    default: () => [],
  },
})
const emit = defineEmits(['onDataChange', 'onReset'])
const appStore = useAppStore()
const $queryForm = ref(null)
const treatedColumns = computed(() => {
  const selectionItem = props.selection ? [{ type: 'selection', fixed: 'left', width: 40 }] : []
  const indexItem = props.index
    ? [
        {
          title: '序号',
          width: props.indexWidth,
          key: 'index',
          fixed: 'left',
          render: (_, index) => index + 1,
        },
      ]
    : []
  return [
    ...selectionItem,
    ...indexItem,
    ...props.columns.map((item) => ({
      ...item,
      width: item.width || props.cellWidth,
      ellipsis: {
        tooltip: {
          style: {
            maxWidth: `${props.tooltipWidth}px`,
          },
        },
      },
    })),
  ]
})
const scrollX = computed(() => treatedColumns.value.reduce((sum, { width }) => (sum += width), 0))
const loading = ref(false)
const tableData = ref([])
const pagination = reactive({
  page: 1,
  pageSize: 10,
  itemCount: 0,
  showSizePicker: true,
  showQuickJumper: true,
  pageSizes: [10, 20, 30, 40],
  displayOrder: ['size-picker', 'pages', 'quick-jumper'],
  onChange: (currentPage) => {
    pagination.page = currentPage
    if (props.remote) {
      handleQuery()
    }
  },
  onUpdatePageSize: (pageSize) => {
    pagination.pageSize = pageSize
    if (props.remote) {
      handleQuery()
    }
  },
  prefix: () => (
    <div class={['text-14 font-400 color-#FFFFFFCC']}>共{pagination.itemCount}项数据。</div>
  ),
  suffix: () => <div class={['text-14 font-400 color-#FFFFFFCC']}>页</div>,
})

/**
 *  依据现有条件查询
 */
async function handleQuery() {
  try {
    loading.value = true
    // 分页相关参数
    let paginationParams = {}
    // 如果非分页模式或者使用前端分页,则无需传分页参数
    if (props.isPagination && props.remote) {
      paginationParams = { current: pagination.page, size: pagination.pageSize }
    }
    // 查询项表单参数
    const otherParams = $queryForm.value.getQueryParams()
    const { data } = await props.getData({
      ...otherParams,
      ...paginationParams,
    })
    tableData.value = data?.records || data
    pagination.itemCount = Number(data.total ?? data.length)
  } catch (error) {
    tableData.value = []
    pagination.itemCount = 0
  } finally {
    emit('onDataChange', tableData.value)
    loading.value = false
  }
}

/**
 *  依据现有条件，重新从第一页查询
 */
function handleSearch() {
  pagination.page = 1
  handleQuery()
}

/**
 *  重置查询条件，并从第一页查询
 */
async function handleReset() {
  $queryForm.value.initQueryItems()
  nextTick(() => {
    emit('onReset')
    handleSearch()
  })
}

onMounted(() => {
  // 等待可能加载的默认查询项
  $queryForm.value.initQueryItems()
  // 自动请求
  props.autoLoad && handleQuery()
})

function handleExport(columns = props.columns, data = tableData.value) {
  if (!data?.length) return $message.warning('没有数据')
  const columnsData = columns.filter((item) => !!item.title && !item.hideInExcel)
  const thKeys = columnsData.map((item) => item.key)
  const thData = columnsData.map((item) => item.title)
  const trData = data.map((item) => thKeys.map((key) => item[key]))
  const sheet = utils.aoa_to_sheet([thData, ...trData])
  const workBook = utils.book_new()
  utils.book_append_sheet(workBook, sheet, '数据报表')
  writeFile(workBook, '数据报表.xlsx')
}

function renderCell(value) {
  if ([undefined, null, ''].includes(value)) {
    return '—'
  } else {
    return value
  }
}

defineExpose({
  // 不重置查询项，从当前页查
  handleQuery,
  // 不重置查询项，从第1页查
  handleSearch,
  // 重置查询项，从第1页查
  handleReset,
  handleExport,
})
</script>
<style lang="scss" scoped>
// .crud-table.deep :deep() {
//   --gap-y: 8px;
//   .n-data-table-table {
//     border-spacing: 4px 0;
//   }
//   .n-data-table-base-table-header {
//     margin-bottom: var(--gap-y);
//   }
//   .n-data-table-th {
//     background: rgba(49, 152, 228, 0.16);
//     border-radius: 2px;
//     padding: 0 24px !important;
//     height: 34px !important;
//     line-height: 34px !important;
//   }
//   .n-data-table-td {
//     padding: 0 24px var(--gap-y) !important;
//     height: calc(40px + var(--gap-y)) !important;
//     vertical-align: middle;
//   }
//   .n-data-table-tbody .n-data-table-tr:hover {
//     position: relative;
//     .n-data-table-td:nth-child(1) {
//       &::before {
//         content: '';
//         position: absolute;
//         z-index: -1;
//         top: 0;
//         left: 0;
//         display: block;
//         width: 10px;
//         height: 40px;
//         background: #51e6fb;
//         border-radius: 2px;
//       }
//       &::after {
//         content: '';
//         position: absolute;
//         z-index: -1;
//         top: 0;
//         left: 12px;
//         display: block;
//         width: calc(100% - 12px);
//         height: 40px;
//         box-shadow: inset 0px 0px 9px 0px #51e6fb;
//         border-radius: 2px;
//         background: #3198e433;
//       }
//     }
//   }
// }
// :deep(.n-data-table__pagination) {
//   flex-shrink: 0;
//   position: relative;
//   .n-pagination-prefix {
//     position: absolute;
//     left: 0;
//     top: 50%;
//     transform: translateY(-50%);
//     font-size: 14px;
//     color: #686f7c;
//   }
//   .n-pagination-item--button {
//     background: none !important;
//     border: none !important;
//   }
// }
</style>
